///////////////////////////////////////////////////////////////////////
// DiscFormatEraseEvent.cpp
//
// Wrapper for DDiscFormat2EraseEvents Interface Events
//
// Written by Nic Wilson
//

#include "stdafx.h"
#include "DiscFormatEraseEvent.h"

#include "DiscFormatErase.h"

// CDiscFormatEraseEvent

IMPLEMENT_DYNAMIC(CDiscFormatEraseEvent, CCmdTarget)

BEGIN_INTERFACE_MAP(CDiscFormatEraseEvent, CCmdTarget)
	INTERFACE_PART(CDiscFormatEraseEvent, IID_IDispatch, FormatEraseEvents)
	INTERFACE_PART(CDiscFormatEraseEvent, IID_DDiscFormat2EraseEvents, FormatEraseEvents)
END_INTERFACE_MAP()

CDiscFormatEraseEvent::CDiscFormatEraseEvent()
: m_hNotifyWnd(NULL)
, m_ptinfo(NULL)
, m_dwCookie(0)
, m_pUnkSink(0)
, m_pUnkSrc(0)
{
}

CDiscFormatEraseEvent::~CDiscFormatEraseEvent()
{
	if (m_dwCookie && (m_pUnkSrc != NULL) && (m_pUnkSink != NULL))
	{
		AfxConnectionUnadvise(m_pUnkSrc, IID_DDiscFormat2EraseEvents, m_pUnkSink, TRUE, m_dwCookie);
	}
}


BEGIN_MESSAGE_MAP(CDiscFormatEraseEvent, CCmdTarget)
END_MESSAGE_MAP()



// CDiscFormatEraseEvent message handlers

ULONG FAR EXPORT CDiscFormatEraseEvent::XFormatEraseEvents::AddRef()
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	return pThis->ExternalAddRef();
}
ULONG FAR EXPORT CDiscFormatEraseEvent::XFormatEraseEvents::Release()
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	return pThis->ExternalRelease();
}
STDMETHODIMP CDiscFormatEraseEvent::XFormatEraseEvents::QueryInterface(REFIID riid,
												   LPVOID FAR* ppvObj)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	return (HRESULT)pThis->ExternalQueryInterface(&riid, ppvObj);
}
STDMETHODIMP
CDiscFormatEraseEvent::XFormatEraseEvents::GetTypeInfoCount(UINT FAR* pctinfo)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	*pctinfo = 1;
	return NOERROR;
}
STDMETHODIMP CDiscFormatEraseEvent::XFormatEraseEvents::GetTypeInfo(
	UINT itinfo,
	LCID lcid,
	ITypeInfo FAR* FAR* pptinfo)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	*pptinfo = NULL;

	if(itinfo != 0)
		return ResultFromScode(DISP_E_BADINDEX);
	pThis->m_ptinfo->AddRef();
	*pptinfo = pThis->m_ptinfo;
	return NOERROR;
}
STDMETHODIMP CDiscFormatEraseEvent::XFormatEraseEvents::GetIDsOfNames(
	REFIID riid,
	OLECHAR FAR* FAR* rgszNames,
	UINT cNames,
	LCID lcid,
	DISPID FAR* rgdispid)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	return DispGetIDsOfNames(pThis->m_ptinfo, rgszNames, cNames, rgdispid);
}

STDMETHODIMP CDiscFormatEraseEvent::XFormatEraseEvents::Invoke(
	DISPID dispidMember,
	REFIID riid,
	LCID lcid,
	WORD wFlags,
	DISPPARAMS FAR* pdispparams,
	VARIANT FAR* pvarResult,
	EXCEPINFO FAR* pexcepinfo,
	UINT FAR* puArgErr)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)

	return DispInvoke(&pThis->m_xFormatEraseEvents, pThis->m_ptinfo,
		dispidMember, wFlags, pdispparams, pvarResult, pexcepinfo, puArgErr);
}

//
///////////////////////////////////////////////////////////////////////
//
// CDiscFormatEraseEvent::CreateEventSink
//
// Description:
//			Establishes a link between the CDiscFormatErase(IDiscFormat2Erase)
//			and the CDiscFormatEraseEvent(DDiscFormat2EraseEvents) so 
//			CDiscFormatEraseEvent can receive Update messages
//
CDiscFormatEraseEvent* CDiscFormatEraseEvent::CreateEventSink()
{
	// Create the event sink
	CDiscFormatEraseEvent* pDiscFormatEraseEvent = new CDiscFormatEraseEvent();

	pDiscFormatEraseEvent->EnableAutomation();
	pDiscFormatEraseEvent->ExternalAddRef();

	return pDiscFormatEraseEvent;
}

///////////////////////////////////////////////////////////////////////
//
// CDiscFormatEraseEvent::ConnectDiscFormatErase
//
// Description:
//			Establishes a connection between the CDiscFormatErase(IDiscFormat2Erase)
//			and the CDiscFormatEraseEvent(DDiscFormat2EraseEvents) so 
//			CDiscFormatEraseEvent can receive Update messages
//
bool CDiscFormatEraseEvent::ConnectDiscFormatErase(CDiscFormatErase* pDiscFormatErase)
{
	m_pUnkSink = GetIDispatch(FALSE);
	m_pUnkSrc = pDiscFormatErase->GetInterface();

	LPTYPELIB ptlib = NULL;
	HRESULT hr = LoadRegTypeLib(LIBID_IMAPILib2, IMAPILib2_MajorVersion, IMAPILib2_MinorVersion, LOCALE_SYSTEM_DEFAULT, &ptlib);
	if (FAILED(hr))
	{
		return false;
	}
	hr = ptlib->GetTypeInfoOfGuid(IID_DDiscFormat2EraseEvents, &m_ptinfo);
    ptlib->Release();
	if (FAILED(hr))
	{
	    return false;
	}

	BOOL bRet = AfxConnectionAdvise(m_pUnkSrc, IID_DDiscFormat2EraseEvents, m_pUnkSink,
		TRUE, &m_dwCookie);
	if (bRet)
	{
		return true;
	}

	return false;
}

///////////////////////////////////////////////////////////////////////
//
// CDiscFormatEraseEvent::Update
//
// Description:
//			Receives update notifications from IDiscFormat2Erase
//
STDMETHODIMP_(HRESULT) CDiscFormatEraseEvent::XFormatEraseEvents::Update(IDispatch* objectDispatch, LONG elapsedSeconds, LONG expectedSeconds)
{
	METHOD_PROLOGUE(CDiscFormatEraseEvent, FormatEraseEvents)
	HRESULT hr = S_OK;

	IDiscFormat2Erase* discFormatErase = NULL;
    hr = objectDispatch->QueryInterface(IID_PPV_ARGS(&discFormatErase));

    IMAPI_STATUS imapiStatus = {0};
	
	imapiStatus.elapsedTime = elapsedSeconds;
	imapiStatus.totalTime = expectedSeconds;
	imapiStatus.remainingTime = expectedSeconds-elapsedSeconds;
	LRESULT ret = ::SendMessage(pThis->m_hNotifyWnd, WM_IMAPI_UPDATE, IMAPI_FORMAT2_DATA_WRITE_ACTION_FORMATTING_MEDIA, (LPARAM)(LPVOID)&imapiStatus);
	return S_OK;
}

